import huawei_test_constants as constants
import requests
import asyncio
import aiohttp
import re
from openpyxl import Workbook, load_workbook
from pyppeteer_check_url import check_main

current_language = 'cn'
guides_contents_json, guides_dict, topic_info_results = {}, {}, []
data = {}


def get_url_json(url, catalog_name, object_id, language):
    global data
    data = {'language': language, 'catalogName': catalog_name, 'objectId': object_id}
    response = requests.post(url=url, headers=constants.headers, data=data, verify=False)
    return response.json()


def get_topic_info(choose, catalog_name, queue):
    for tree in guides_contents_json['value']['catalogTreeList']:
        get_topic(tree, 1, queue)
    try:
        asyncio.get_event_loop().run_until_complete(get_href_by_object_id(catalog_name, queue))
    except Exception as e:
        queue.put(e)
    write_to_excel(choose)


async def get_href_by_object_id(catalog_name, queue):
    # 设置允许同时运行的协程数量
    max_concurrent = constants.MAX_SEMAPHORE
    semaphore = asyncio.Semaphore(max_concurrent)

    async with aiohttp.ClientSession() as session:
        tasks = [asyncio.create_task(get_document(session, index, topic_info, semaphore, catalog_name, queue)) for
                 index, topic_info in enumerate(topic_info_results)]
        await asyncio.wait(tasks)


async def get_document(session, index, topic_info, semaphore, catalog_name, queue):
    """
    异步方式获取文档内容
    :param session: aiohttp.ClientSession()
    :param index: 当前所在结果中的索引
    :param topic_info: topic相关信息
    :param semaphore: 限制线程数量
    :param catalog_name: catalog_name
    :param queue
    :return:
    """
    if topic_info['topic_url'] != '':
        object_id = topic_info['topic_url'].split('/')[-1]
        async with semaphore:
            current_data = {'language': current_language, 'catalogName': catalog_name, 'objectId': object_id,
                            'version': ''}

            async with session.post(url=constants.GET_DOCUMENT_BY_ID, headers=constants.headers, data=current_data) as response:
                res = await response.json()
                html = res['value']['content']['content']
                parse_html(html, index, topic_info['topic_url'], queue)


def parse_html(html_content, index, current_url, queue):
    """
    解析html
    :param index: 在topic_info_results中索引
    :param html_content:
    :param current_url:
    :param queue:
    :return:
    """
    topic_info_results[index]['href'] = []
    pattern = r'<a\s+href="([^"]*)"[^>]*>([^<]*)</a>'
    matches = re.finditer(pattern, html_content)
    for match in matches:
        url = match.group(1)
        if url.startswith("#"):
            url = current_url + f'{url}'
        text = match.group(2)
        topic_info_results[index]['href'].append({text: url})
        queue.put(f"{topic_info_results[index]['nodeName']}: {text}--{url}")


def write_to_excel(choose):
    wb = Workbook()
    my_sheet = wb.worksheets[0]
    max_level = 0
    for topic_info in topic_info_results:
        if topic_info['level'] >= max_level:
            max_level = topic_info['level']
    first_row = []
    for i in range(max_level):
        first_row.append(f'topic_level{i + 1}')

    first_row.append('topic地址')
    first_row.append('超链接信息')
    first_row.append('超链接地址')
    my_sheet.append(first_row)
    for topic_info in topic_info_results:
        if topic_info['topic_url'] == "":
            my_sheet.append([topic_info['nodeName']])
        else:
            topic_level = topic_info['level']
            current_row = [''] * (topic_level - 1)
            current_row.append(topic_info['nodeName'])
            current_row = current_row + [''] * (max_level - topic_level) + [topic_info['topic_url']]

            for href in topic_info['href']:
                for k, v in href.items():
                    current_row = current_row + [k] + [v]
                    my_sheet.append(current_row)
                    topic_level = topic_info['level']
                    current_row = [''] * (topic_level - 1)
                    current_row.append(topic_info['nodeName'])
                    current_row = current_row + [''] * (max_level - topic_level) + [topic_info['topic_url']]
    wb.save(f'超链接_{choose}.xlsx')


def get_topic(tree_dict: dict, level, queue):
    """
    获取topic信息
    :param tree_dict:
    :param level:
    :param queue:
    :return: [{'nodeName': '应用体验建议', 'level': 1, 'topic_url': '', 'sections': []}, {...}]
    """
    if level == 1:
        queue.put(f'{tree_dict["nodeName"]} level-{level}')
        topic_info_results.append({"nodeName": tree_dict['nodeName'], 'level': level, "topic_url": ''})
    else:
        queue.put(
            f"{tree_dict['nodeName']},level-{level},{constants.HUAWEI_URL_PREFIX[current_language]}/{data['catalogName']}/{tree_dict['relateDocument']}")
        topic_info_results.append({"nodeName": tree_dict['nodeName'], 'level': level,
                                   "topic_url": f'{constants.HUAWEI_URL_PREFIX[current_language]}/{data["catalogName"]}/{tree_dict["relateDocument"]}'})
    if len(tree_dict['children']) != 0:
        for child in tree_dict['children']:
            get_topic(child, level + 1, queue)
    else:
        return topic_info_results


def result_write_to_excel(file_path, result, offset):
    rb = load_workbook(file_path)
    rs = rb.worksheets[0]
    for row in rs.iter_rows(min_row=2, values_only=False):
        last_cell = row[-1]
        new_cell = last_cell.offset(column=1)
        if row[offset].value:
            new_cell.value = result[row[offset].value]
            # 问题分类
            question = new_cell.value
            if 'Failed' in question:
                question_classify_cell = new_cell.offset(column=1)
                if '重定向' in question:
                    question_classify_cell.value = '链接重定向问题'
                elif '未正确跳转到锚点' in question:
                    question_classify_cell.value = '链接未跳转到正确锚点'
                elif '404' in question or '403' in question or '400' in question or '504' in question:
                    question_classify_cell.value = '链接不存在'
                else:
                    question_classify_cell.value = '待确认'

    # rs['E1'] = '结果'
    # rs['F1'] = '问题分类'
    rb.save(file_path)


def main(queue, test_mode, language, product):
    global guides_contents_json, guides_dict, topic_info_results, current_language
    current_language = language
    queue.put(f'Start getting hyperlinks')
    if product == '指南':
        catalog_name = constants.CATALOG_NAME_GUIDES
        guides_contents_json = get_url_json(constants.GET_CATALOG_TREE, catalog_name,
                                            constants.OBJECT_ID_GUIDES, current_language)
        get_topic_info(product, catalog_name, queue)
    elif product == '最佳实践':
        catalog_name = constants.CATALOG_NAME_BEST_PRACTICES
        guides_contents_json = get_url_json(constants.GET_CATALOG_TREE, catalog_name,
                                            constants.OBJECT_ID_BEST_PRACTICES, current_language)
        get_topic_info(product, catalog_name, queue)
    elif product == 'API':
        catalog_name = constants.CATALOG_NAME_API
        guides_contents_json = get_url_json(constants.GET_CATALOG_TREE, catalog_name,
                                            constants.OBJECT_ID_API, current_language)
        get_topic_info(product, catalog_name, queue)
    elif product == 'FAQ':
        catalog_name = constants.CATALOG_NAME_FAQ
        guides_contents_json = get_url_json(constants.GET_CATALOG_TREE, catalog_name,
                                            constants.OBJECT_ID_FAQ, current_language)
        get_topic_info(product, catalog_name, queue)
    elif product == '版本说明':
        catalog_name = constants.CATALOG_NAME_OVERVIEW
        guides_contents_json = get_url_json(constants.GET_CATALOG_TREE, catalog_name,
                                            constants.OBJECT_ID_OVERVIEW, current_language)
        get_topic_info(product, catalog_name, queue)

    result, target_index = check_main(f'超链接_{product}.xlsx', queue, test_mode)
    result_write_to_excel(f'超链接_{product}.xlsx', result, target_index)


if __name__ == '__main__':
    main()